package com.googlecode.olabs.gui.client.resources;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.googlecode.olabs.gui.client.rest.AbstractRestResource;
import com.googlecode.olabs.gui.client.rest.ResourceObserver;
import com.googlecode.olabs.gui.client.rest.RestRequestBuilder;
import com.googlecode.olabs.gui.client.rest.RestResource;

public class CardCollection extends AbstractRestResource implements
		ResourceObserver {

	public static final String URL = "/cards";

	private final Map<String, Card> m_cards;

	private RestRequestBuilder m_getRequestBuilder;

	public CardCollection() {
		super();
		m_cards = new HashMap<String, Card>();
	}

	public void flushCards() {
		m_cards.clear();
	}

	public Collection<Card> getCards() {
		return m_cards.values();
	}

	public Card getCard(String id) {
		return m_cards.get(id);
	}

	public void refreshCards() {
		if (m_getRequestBuilder == null) {
			m_getRequestBuilder = RestRequestBuilder.create(
					RestRequestBuilder.GET, URL);
		}
		try {
			m_getRequestBuilder.sendRequest(new RequestCallback() {
				public void onError(Request request, Throwable exception) {
					Window.alert("Error completing call: " + exception);
				}

				public void onResponseReceived(Request request,
						Response response) {
					if (response.getStatusCode() == Response.SC_OK) {
						refreshCards(response.getText());
					}
				}
			});
		} catch (RequestException e) {
			Window.alert("Exception trying to make call: " + e);
		}
	}

	private void refreshCards(String cards) {
		for (String cardText : parseResponse(cards)) {
			if (!m_cards.containsKey(cardText)) {
				Card card = new Card(cardText);
				card.addResourceObserver(this);
				m_cards.put(cardText, card);
			}
		}
		notifyObservers();
	}

	private String[] parseResponse(String response) {
		JSONValue responseObject = JSONParser.parse(response);
		if (responseObject == null) {
			return null;
		}
		JSONArray array = responseObject.isArray();
		if (array == null) {
			return null;
		}
		String[] result = new String[array.size()];
		for (int i = 0; i < array.size(); i++) {
			JSONValue value = array.get(i);
			JSONString string = value.isString();
			if (string == null) {
				return null;
			}
			result[i] = string.stringValue();
		}
		return result;
	}

	public void resourceChanged(RestResource resource) {
		notifyObservers();
	}
}
